#ifndef AFCORE_DATABASE_DATABASE_DATABSE_TRANSACTION_
#define AFCORE_DATABASE_DATABASE_DATABSE_TRANSACTION_

#include <mutex>
#include <vector>

#include "define.h"
#include "database_sql_op.h"
#include "database_fwd.h"
#include "stringformat.h"

namespace afcore {

/// @brief  数据库
namespace database {

/// @brief  事务 基类
class AFCORE_DATABASE_API CTransactionBase {
  friend class CTransactionTask;
  friend class CMysqlConnection;

  template <typename T> friend class CDatabaseWorkerPool;
public:
  /// @brief  构造函数
  CTransactionBase() = default;
  /// @brief  析构函数
  virtual ~CTransactionBase() { CleanUp(); }

  /// @brief  追加事务
  /// @param  sql         sql语句
  void Append(const char* sql);

  /// @brief  追加事务 格式化字符串
  /// @tparam Format      格式化
  /// @tparam ...Args     格式化参数
  /// @param  sql         格式化语句
  /// @param  ...args     格式化语句参数
  template<typename Format, typename... Args>
  void PAppend(Format&& sql, Args&&... args) {
    Append(StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
  }

  /// @brief  返回事务的大小
  [[nodiscard]] size_t GetSize() const { return queries_.size(); }

protected:
  /// @brief  追加预处理语句
  /// @param  stmt        预处理语句
  void AppendPreparedStatment(CPreparedStatementBase* stmt);
  /// @brief  清理
  void CleanUp();
protected:
  std::vector<SSqlElementData> queries_;  ///< 事务数据集合
private:
  bool cleaned_up_ {false};               ///< 清理标志
};

/// @brief  事务
template<typename T>
class CTransaction
  : public CTransactionBase {
public:
  using CTransactionBase::Append;
  /// @brief  追加T类型的预处理语句
  /// @note   此处为重载不是重写
  void Append(CPreparedStatement<T>* stmt) {
    AppendPreparedStatment(stmt);
  }
};

/// @brief  事务任务
class AFCORE_DATABASE_API CTransactionTask
  : public CSqlOperation {
  template <typename T> friend class CDatabaseWorkerPool;
  friend class CDatabaseWorker;
public:
  /// @brief  构造函数
  CTransactionTask(std::shared_ptr<CTransactionBase> trans)
    : trans_(trans) {}
  /// @brief  析构函数
  ~CTransactionTask() = default;
protected:
  /// @brief  任务执行 重写
  /// @return true    事务任务成功
  /// @return true    事务任务失败
  bool Execute() override;
protected:
  std::shared_ptr<CTransactionBase> trans_; ///< 事务集合
  static std::mutex deadlock_mutex_;        ///< 死锁互斥锁
};

} // !namespace database

} // !namespace afcore

#endif //! AFCORE_DATABASE_DATABASE_DATABSE_TRANSACTION_